package com.xiaozhi.controller;

import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Map;

//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ServerWebExchange;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.xiaozhi.common.config.WxMaProperties;
import com.xiaozhi.common.config.WxPayProperties;
import com.xiaozhi.common.context.UserTokenContextHolder;
import com.xiaozhi.common.web.AjaxResult;
import com.xiaozhi.entity.BussinessCombo;
import com.xiaozhi.entity.PersionCombo;
import com.xiaozhi.entity.WxOrder;
import com.xiaozhi.entity.WxPayOrder;
import com.xiaozhi.service.PersionComboService;
import com.xiaozhi.service.WxOrderServer;
import com.xiaozhi.service.WxPayOrderService;
import com.xiaozhi.service.WxUserService;
import com.xiaozhi.vo.UserTokenVO;

import cn.hutool.extra.servlet.ServletUtil;

//import cn.hutool.extra.servlet.ServletUtil;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;


@RestController
@AllArgsConstructor
@Slf4j
@RequestMapping("/wx/api/payment")
public class WxPaymentController {

    @Autowired
    private  WxPayProperties wxPayProperties;

    @Autowired
    private WxMaProperties wxMaProperties;


    @Autowired
    private WxUserService wxUserService;

    @Autowired
    private WxPayOrderService wxPayOrderService;

    @Autowired
    private WxPayService  wxPayService;

    @Autowired
    private WxOrderServer wxOrderServer;

    @Autowired
    private PersionComboService persionComboService;

    @PostMapping("/user/createOrder")
    public Mono<AjaxResult> createOrder(@RequestBody  WxOrder wxOrder,ServerWebExchange exchange)  throws WxPayException{
        String bed_id = "123456789";
        log.info("参数的bed_id：{}", bed_id);
        if (StringUtils.isAnyBlank(bed_id)) {
            AjaxResult result = AjaxResult.error();
            result.put("data", "参数不能为null");
            return Mono.just(result);
        }
        // TODO 插入订单记录
        // TODO 记录用户的购买记录
        // TODO 调用统一生成订单接口
        String token = UserTokenContextHolder.GetUserTokenFromWebExchange(exchange);;
        UserTokenVO user = wxUserService.getUserFromToken(token);
        String openId = user.getOpenId();
        String order_No = UserTokenContextHolder.generateOrderNo();

        wxOrder.setOrderId(order_No);
        wxOrder.setOpenId(openId);
        wxOrder.setState(0);
        // 订单插入数据库
        wxOrderServer.add(wxOrder);


        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
        log.info("appid:"+wxMaProperties.getConfigs().get(0).getAppid());
       // orderRequest.setAppid(wxMaProperties.getConfigs().get(0).getAppid());
       orderRequest.setAppid("wx845e4ed20b8e5b7b");
       // orderRequest.setSignType(WxPayConstants.SignType.HMAC_SHA256);
        orderRequest.setBody("腾讯充值中心-QQ会员充值");
        orderRequest.setOutTradeNo(order_No); //自己生成order_No
        orderRequest.setTradeType(WxPayConstants.TradeType.JSAPI);
//        orderRequest.setTotalFee(BaseWxPayRequest.yuanToFen(yuanMoney));//直接分
        log.info("wxOrder:"+wxOrder.getTotalPrice()*100);
        orderRequest.setTotalFee(1);//直接分
        orderRequest.setOpenid(openId); // 获取微信支付用户的openId
        ServerHttpRequest request = exchange.getRequest();
        orderRequest.setSpbillCreateIp( request.getRemoteAddress().getAddress().getHostAddress());
        Date now = new Date();
        Date afterDate = DateUtils.addMinutes(now, 10);//10分钟后
        orderRequest.setTimeStart(DateFormatUtils.format(now,"yyyyMMddHHmmss"));
        orderRequest.setTimeExpire( DateFormatUtils.format(afterDate, "yyyyMMddHHmmss"));
        orderRequest.setNotifyUrl(wxPayProperties.getNotifyUrl()+"/wx/api/payment/notify");
        Object order = wxPayService.createOrder(orderRequest);
        AjaxResult result = AjaxResult.success();
        result.put("data", order);
        return Mono.just(result);
        //return R.ok().put("order", order);
    }
// /*
//     @ResponseBody
//     @PostMapping("/notify")
//     public String payNotify(HttpServletRequest request, HttpServletResponse response) throws IOException, WxPayException {
//       String xmlData = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
//       log.info("支付回调：" + xmlData);        //微信支付服务
//       //WxPayService wxPayService = WxPayConfiguration.getPayService();       
//       WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
//       log.info("支付回调解析结果" + notifyResult);        //对创建的订单进行支付
//       WxPayOrder sysOrders = wxPayOrderService.getOne( new LambdaQueryWrapper<WxPayOrder>()
//                                                       .eq(WxPayOrder::getOrderNo, notifyResult.getOutTradeNo()),
//                                                       false);        
//       if (sysOrders != null) {            
//         if (sysOrders.getOrderAmount().multiply(new BigDecimal("1.0")).intValue() == notifyResult.getTotalFee()){  
//                 String timeEnd = notifyResult.getTimeEnd();                 
//                 LocalDateTime paymentTime = LocalDateTime.parse(timeEnd);                 //支付时间
//                  sysOrders.setPaymentTime(paymentTime);
//                  sysOrders.setOrderAmount(sysOrders.getOrderAmount());                 //微信订单编号
//                  sysOrders.setTransactionId(notifyResult.getTransactionId());                 //更新数据库
//                 // wxPayOrderService.notifyOrder(sysOrders);
//                  log.info("支付回调成功通知：" + sysOrders.getOrderNo());                 
//                  return WxPayNotifyResponse.success("支付成功");
//             } else {                
//                return WxPayNotifyResponse.fail("付款金额与订单金额不符");
//             }
//         } 
//         else {            
//           return WxPayNotifyResponse.fail("无此订单");
//         }

//      // try {

//         /*HttpSession session = request.getSession();
//         String mobile = (String) session.getAttribute("userphone");
//         if (StringUtils.isBlank(mobile)) {
//             return R.error(401, "session获取不到授权手机号！");
//         }
//           //获取用户手机号,根据用户手机号获取用户ID
//           AuthorizationEntity user = authorizationService.getOneByMobile(mobile);*/
//        /* String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
//         WxPayOrderNotifyResult notifyResult = wxService.parseOrderNotifyResult(xmlResult);
//         // 结果正确 outTradeNo
//         String orderId = notifyResult.getOutTradeNo();
//         String tradeNo = notifyResult.getTransactionId();
//         String totalFee = BaseWxPayResult.fenToYuan(notifyResult.getTotalFee());
//         if("SUCCESS".equals(notifyResult.getResultCode())) {
//             PayFlowEntity entity = new PayFlowEntity();
//             entity.setPayFee(BigDecimal.valueOf(notifyResult.getCashFee()));
//             entity.setPayFlowNo(orderId);
//             entity.setPayUserInfo(notifyResult.getOpenid());
//             entity.setThreeInNo(tradeNo);
//             payFlowService.save(entity);
//             OrderEntity order_entity = new OrderEntity();
//             SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
//             order_entity.setCreateTime(new Date());
//             //更新订单信息
//             UpdateWrapper<OrderEntity> updateWrapper = new UpdateWrapper<>();
//             updateWrapper.set("order_status", "1");
//             updateWrapper.set("pay_id", notifyResult.getOpenid());
//             updateWrapper.set("pay_status", "1");
//             updateWrapper.set("pay_end_time", sdf.parse(notifyResult.getTimeEnd()));
//             updateWrapper.eq("order_no",notifyResult.getOutTradeNo());
//             orderService.update(updateWrapper);
//         }
//         //自己处理订单的业务逻辑，需要判断订单是否已经支付过，否则可能会重复调用
//          return WxPayNotifyResponse.success("成功");
//       } catch (Exception e) {
//         log.error("微信回调结果异常,异常原因{}", e.getMessage());
//        // WxPayNotifyResponse.fail(e.getMessage());

//         return WxPayNotifyResponse.success("code:"+9999+"微信回调结果异常,异常原因:"+e.getMessage());

//       }*/
//     //  return "";
//    // } 
//    // catch(Exception e){
//    //     return "";
//   //  }
//     }
// */
    @PostMapping(value = "/notify", consumes = MediaType.APPLICATION_XML_VALUE)
    public Mono<AjaxResult> payNotify(ServerWebExchange exchange) throws IOException, WxPayException{
        // 读取请求体（XML 数据）
        return exchange.getRequest().getBody()
            .reduce((data1, data2) -> {
                byte[] merged = new byte[data1.readableByteCount() + data2.readableByteCount()];
                data1.read(merged);
                data2.read(merged, data1.readableByteCount(), data2.readableByteCount());
                return data1.factory().wrap(merged);
            })
            .map(dataBuffer -> {
                String xmlData = dataBuffer.toString(StandardCharsets.UTF_8);
                //dataBuffer.release(); // 释放资源
                return xmlData;
            })
            .flatMap(xmlData -> {
                log.info("支付回调：" + xmlData);
                // 解析微信支付通知结果（同步操作，可考虑放到异步线程池）
                return Mono.fromCallable(() -> {
                    try {
                        WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
                        log.info("支付回调解析结果" + notifyResult);
                        //         // 结果正确 outTradeNo
                        String orderId = notifyResult.getOutTradeNo();
                        String tradeNo = notifyResult.getTransactionId();
                        String totalFee = BaseWxPayResult.fenToYuan(notifyResult.getTotalFee());
                        if("SUCCESS".equals(notifyResult.getResultCode())) {
                            //检查状态和金额
                            // 更新订单状态和我的套餐

                            log.info("pay callback success,orderId:"+orderId);
                            WxOrder order = wxOrderServer.selectOrderByorderId(orderId);
                            if(order!= null)
                            {
                                order.setState(2);
                                wxOrderServer.update(order);
                                persionComboService.add_persion_combo(order);

                            }
                            else{
                                log.error("no order :"+order.getOrderId());
                            }
                        }

                        return AjaxResult.success();
                    } catch (Exception e) {
                        log.error(e.getMessage(), e);
                        return AjaxResult.error();
                    }
                });

                // return Mono.fromCallable(() -> wxPayService.parseOrderNotifyResult(xmlData))
                //     .flatMap(notifyResult -> {
                //         log.info("支付回调解析结果：" + notifyResult);
                        
                //         // 查询订单（假设 wxPayOrderService 是响应式的）
                //         return wxPayOrderService.getOne(
                //             new LambdaQueryWrapper<WxPayOrder>()
                //                 .eq(WxPayOrder::getOrderNo, notifyResult.getOutTradeNo())
                //         )
                //         .switchIfEmpty(Mono.error(new IllegalArgumentException("无此订单")))
                //         .flatMap(sysOrders -> {
                //             // 验证金额
                //             if (sysOrders.getOrderAmount().multiply(new BigDecimal("1.0")).intValue() == notifyResult.getTotalFee()) {
                //                 String timeEnd = notifyResult.getTimeEnd();
                //                 LocalDateTime paymentTime = LocalDateTime.parse(timeEnd);
                                
                //                 // 更新订单信息
                //                 sysOrders.setPaymentTime(paymentTime);
                //                 sysOrders.setTransactionId(notifyResult.getTransactionId());
                                
                //                 // 保存更新（假设是响应式方法）
                //                 return wxPayOrderService.notifyOrder(sysOrders)
                //                     .thenReturn(WxPayNotifyResponse.success("支付成功"));
                //             } else {
                //                 return Mono.just(WxPayNotifyResponse.fail("付款金额与订单金额不符"));
                //             }
                //         });
                //     })
                    // .onErrorResume(e -> {
                    //     log.error("处理支付回调失败", e);
                    //     return Mono.just(WxPayNotifyResponse.fail("处理失败: " + e.getMessage()));
                    // });
            });
    }
    
    
    //@ApiOperation(value = "取消订单")
    @PostMapping(value = "/cancel/{orderId}")
    public Mono<AjaxResult> cancel(@PathVariable Long orderId,ServerWebExchange exchange){ 
        //判断订单是否存在
        // SysOrders sysOrders = sysOrdersService.getById(orderId);        
        // if(sysOrders==null){            
        //     return AjaxResult.error("订单不存在");
        // }        //只有未支付的订单能取消
        // if(!CommonConstants.NO.equals(sysOrders.getIsPay())){           
        //      return AjaxResult.error();
        // }
        // sysOrdersService.orderCancel(sysOrders);        
        // return AjaxResult.success();
        return Mono.just(AjaxResult.success());
    }
}
